package com.hcc.cpwxdemo.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Maps;
import com.hcc.cpwxdemo.entity.QyWxApp;
import com.hcc.cpwxdemo.enums.StatusEnum;
import com.hcc.cpwxdemo.handler.*;
import com.hcc.cpwxdemo.service.QyWxAppService;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import me.chanjar.weixin.cp.constant.WxCpConsts;
import me.chanjar.weixin.cp.message.WxCpMessageRouter;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author hcc
 */
@Slf4j
@Configuration
public class WxCpConfiguration {
    //key corpId+agentId
    private static Map<String, WxCpMessageRouter> routers = Maps.newHashMap();
    //key corpId+agentId
    private static Map<String, WxCpService> cpServices = Maps.newHashMap();
    private final LogHandler logHandler;
    private final NullHandler nullHandler;
    private final LocationHandler locationHandler;
    private final MenuHandler menuHandler;
    private final MsgHandler msgHandler;
    private final UnsubscribeHandler unsubscribeHandler;
    private final SubscribeHandler subscribeHandler;
    private final QyWxAppService qyWxAppService;
    private final ContactChangeHandler contactChangeHandler;
    private final EnterAgentHandler enterAgentHandler;

    public WxCpConfiguration(LogHandler logHandler, NullHandler nullHandler, LocationHandler locationHandler, MenuHandler menuHandler
            , MsgHandler msgHandler, UnsubscribeHandler unsubscribeHandler, SubscribeHandler subscribeHandler, QyWxAppService qyWxAppService, ContactChangeHandler contactChangeHandler, EnterAgentHandler enterAgentHandler) {
        this.logHandler = logHandler;
        this.nullHandler = nullHandler;
        this.locationHandler = locationHandler;
        this.menuHandler = menuHandler;
        this.msgHandler = msgHandler;
        this.unsubscribeHandler = unsubscribeHandler;
        this.subscribeHandler = subscribeHandler;
        this.qyWxAppService = qyWxAppService;
        this.contactChangeHandler = contactChangeHandler;
        this.enterAgentHandler = enterAgentHandler;
    }

    public static Map<String, WxCpMessageRouter> getRouters() {
        return routers;
    }

    public static WxCpService getCpService(String corpId, Integer agentId) {
        return cpServices.get(corpId + agentId);
    }

    @PostConstruct
    public void initServices() {
        log.info("qyWX initServices start");
        List<QyWxApp> qyWxApps = qyWxAppService.list(new QueryWrapper<>(new QyWxApp().setStatus(StatusEnum.ENABLE.getCode())));
        if (CollectionUtils.isEmpty(qyWxApps)) {
            log.error("qyWX initServices failed. qqyWxApp list is empty or null");
            return;
        }
        cpServices = qyWxApps.stream().map(a -> {
            val configStorage = new WxCpDefaultConfigImpl();
            //企业id
            configStorage.setCorpId(a.getCorpId());
            //应用id
            configStorage.setAgentId(a.getAgentId());
            //应用密钥
            configStorage.setCorpSecret(a.getAppSecret());
            //应用token
            configStorage.setToken(a.getToken());
            //验签key 用作消息体加解密密钥。
            configStorage.setAesKey(a.getAesKey());
            val service = new WxCpServiceImpl();
            service.setWxCpConfigStorage(configStorage);
            routers.put(a.getCorpId() + a.getAgentId(), this.newRouter(service));
            return service;
        }).collect(Collectors.toMap(service -> service.getWxCpConfigStorage().getCorpId() + service.getWxCpConfigStorage().getAgentId(), a -> a));
        log.info("qyWX initServices end");
    }

    private WxCpMessageRouter newRouter(WxCpService wxCpService) {
        final val newRouter = new WxCpMessageRouter(wxCpService);

        // 记录所有事件的日志 （异步执行）
        newRouter.rule().handler(this.logHandler).next();

        // 自定义菜单事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.MenuButtonType.CLICK).handler(this.menuHandler).end();

        // 点击菜单链接事件（这里使用了一个空的处理器，可以根据自己需要进行扩展）
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.MenuButtonType.VIEW).handler(this.nullHandler).end();

        // 关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SUBSCRIBE).handler(this.subscribeHandler)
                .end();

        // 取消关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.UNSUBSCRIBE)
                .handler(this.unsubscribeHandler).end();

        // 上报地理位置事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.LOCATION).handler(this.locationHandler)
                .end();

        // 接收地理位置消息
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION)
                .handler(this.locationHandler).end();

        // 扫码事件（这里使用了一个空的处理器，可以根据自己需要进行扩展）
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SCAN).handler(this.nullHandler).end();
        //通讯录变更事件
        newRouter.rule().async(true).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxCpConsts.EventType.CHANGE_CONTACT).handler(this.contactChangeHandler).end();
        //进入应用事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxCpConsts.EventType.ENTER_AGENT).handler(this.enterAgentHandler).end();

        // 默认收到消息事件
        newRouter.rule().async(false).handler(this.msgHandler).end();

        return newRouter;
    }
}
